package cn.livingCloud.service.impl;

import cn.livingCloud.dto.*;
import cn.livingCloud.entity.user.AccountPrivilege;
import cn.livingCloud.entity.user.User;
import cn.livingCloud.entity.user.UserAccount;
import cn.livingCloud.repository.AccountPrivilegeMapper;
import cn.livingCloud.repository.UserAccountMapper;
import cn.livingCloud.repository.UserMapper;
import cn.livingCloud.service.UserAccountService;
import cn.livingCloud.service.impl.operation.UserAccountFormDtoUpdater;
import cn.livingCloud.utils.SessionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserAccountServiceImpl implements UserAccountService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserAccountMapper accountMapper;

    @Autowired
    private AccountPrivilegeMapper privilegeMapper;

    public UserAccount getUserAccountByUserName(String username) {
        return userMapper.findUserAccountByUserName(username);
    }

    public AuthenticationInfo login(String username, String password) {
        UserAccount account = userMapper.findUserAccountByUserNamePassword(username, password);
        return account.login();
    }

    @Override
    public AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals, SimpleAuthorizationInfo info) {
        String username = (String) principals.fromRealm(UserAccount.REALM_NAME).iterator().next();
        if (!StringUtils.isEmpty(username)) {
            UserAccount userAccount = this.getUserAccountByUserName(username);
            addPrivilege(userAccount, info);
            return info;
        }
        return null;
    }

    @Override
    @Deprecated
    public AuthenticationInfo loginMember(String memberCode) {
        return null;
    }

    /**
     * 添加账号权限
     *
     * @param userAccount 账号
     * @param info        已有权限列表
     */
    protected void addPrivilege(UserAccount userAccount, SimpleAuthorizationInfo info) {
        info.addRole(userAccount.getRole());
        for (AccountPrivilege accountPrivilege : userAccount.getPrivilegeList()) {
            info.addStringPermission(accountPrivilege.getPermissionAsString());
        }
    }

    //获取所有的账户列表
    @Override
    public void getUserAccountList(UserAccountListDto userAccountListDto) {
        userAccountListDto.addAllList(accountMapper.findUserAccountList(userAccountListDto));
    }

    //更新状态方法
    @Override
    public UserAccountDto updateState(String uuid, boolean state) {
        UserAccount userAccount = accountMapper.findUserAccountByUuid(uuid);
        //如果前台传入执行的状态和数据库的状态相同那么就异常
        if (state == userAccount.isEnable()) {
            throw new IllegalStateException("禁用/启用失败,请检查账号状态是否被禁用/启用!");
        }
        //如果前台的状态和数据库的状态不相同那么就执行当前传入的操作
        userAccount.setEnable(state);
        accountMapper.updateEnable(userAccount);
        return new UserAccountDto(userAccount);
    }

    @Override
    public String updateAccount(UserAccountFormDto formDto) {
        UserAccountFormDtoUpdater updater = new UserAccountFormDtoUpdater(formDto);
        return updater.update();
    }

    @Override
    public void deleteAccount(String uuid) {
        Assert.notNull(uuid);
        UserAccount userAccount = accountMapper.findUserAccountByUuid(uuid);
        if (userAccount.isEnable()) {
            throw new IllegalStateException("账号在[启用]状态下,无法删除!");
        } else {
            privilegeMapper.deleteAccountPrivilege(uuid);
            accountMapper.deleteAccount(uuid);

            userAccount.getPrivilegeList().clear();
        }
    }

    @Override
    public void updatePassword(AccountChangePasswordDto accountDto) {
        UserAccount userAccountByUuid = accountMapper.findUserAccountByUuid(accountDto.getUuid());
        userAccountByUuid.setPassword(accountDto.getNewPassword());
        accountMapper.updatePassword(userAccountByUuid);
    }

    @Override
    public AccountChangePasswordDto findUserAccountDtoByUuid(String uuid) {
        return new AccountChangePasswordDto(accountMapper.findUserAccountByUuid(uuid));
    }

    @Override
    public void changeSelfPwd(ChangePasswordDto dto) {
        UserAccount account = (UserAccount) SessionUtils.getCurrentUserAccount();
        UserAccount newAccount = accountMapper.findUserAccountByUuid(account.getUuid());
        dto.update(newAccount);
        accountMapper.updatePassword(newAccount);
    }

    @Override
    public boolean checkPassword(String oldPassword) {
        UserAccount account = (UserAccount) SessionUtils.getCurrentUserAccount();
        return account.getPassword().equals(oldPassword);
    }

    @Override
    public boolean check(String username) {
        List<UserAccount> userAccounts = accountMapper.checkUserName(username);
        return userAccounts.size() > 0;
    }

    @Override
    public List<UserDto> searchUserList(String key) {
        List<UserDto> dtoList = new ArrayList<>();
        List<User> users = userMapper.searchUserList(key);
        for (User user : users) {
            dtoList.add(new UserDto(user));
        }
        return dtoList;
    }

    @Override
    public UserAccountFormDto loadUserAccount(UserAccountFormDto formDto) {
        if (StringUtils.isNotEmpty(formDto.getUuid())) {
            UserAccount account = accountMapper.findUserAccountByUuid(formDto.getUuid());
            formDto.load(account);
        }
        if (StringUtils.isNotEmpty(formDto.getUserId())) {
            User user = userMapper.findUserByUuid(formDto.getUserId());
            formDto.setUserDto(new UserDto(user));
        }
        return formDto;
    }
}
